package network;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TcpEchoServer {

    private ServerSocket serverSocket = null;

    public TcpEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动 !");
        while (true) {
            Socket clientSocket = serverSocket.accept();
            // 此处不能直接使用processConnection方法，为每个客户端直接创建一个新线程也不妥
            // 使用线程池，让服务器为多个客户端 提供 服务更好
//            ExecutorService service = Executors.newCachedThreadPool();
//            service.submit(() -> {
                processConnection(clientSocket);
            //});

//            Thread t = new Thread(() -> {
//               processConnection((clientSocket));
//            });
//            t.start();
        }
    }

    private void processConnection(Socket clientSocket) {
        // 打印客户端的信息
        System.out.printf("[%s:%d] 客户端上线!\n", clientSocket.getInetAddress(), clientSocket.getPort());
        try(InputStream is = clientSocket.getInputStream()) {
            try(OutputStream os = clientSocket.getOutputStream()) {
                Scanner inputScanner = new Scanner(is);
                PrintWriter osWriter = new PrintWriter(os);
                // 使用循环 对客户端的请求 持续进行处理
                // 约定以 空格字符 作为一条请求结束的标志, 当客户端程序退出后，scanner.hasNext 会自动识别，并结束循环
                while(inputScanner.hasNext()) {
                    // 1. 使用 scanner 读取客户端发送的请求 并将字节流数据 解析为字符串
                    String request = inputScanner.next();
                    // 2. 服务器对请求作出响应
                    String response = process(request);
                    // 3. 使用 PrintWriter 对 os 进行包裹， 将响应以 字节流的形式 写回到 clientSocket 对象中的 OutputStream
                    // 此处使用 带回车 的数据写入方式， 是方便客户端读取响应时 可直接使用 scanner.nextLine
                    osWriter.println(response);
                    osWriter.flush();
                    // 4. 打印客户端信息 及 请求和响应的内容
                    System.out.printf("[%s:%d], req = %s, resp = %s\n", clientSocket.getInetAddress(),clientSocket.getPort(),
                                        request, response);
                }
                // 客户端退出程序，连接断开，即 while 循环结束
                System.out.printf("[%s:%d] 客户端下线!\n", clientSocket.getInetAddress(), clientSocket.getPort());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 在此处对使用完的 clientSocket 进行关闭
            // processConnection 方法处理完
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    protected String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoServer server = new TcpEchoServer(8080);
        server.start();
    }
}
